
#region Imports

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Text;

using Justa.Model;
using Justa.Data.Entity;
using Justa.Reflection;

#endregion

namespace Justa.Data.Active
{
    /// <summary>
    /// 
    /// </summary>
    /// 
    public abstract class ActiveRecord<T>
    {
        /// <summary>
        /// 
        /// </summary>
        /// 
        private string entityName;

        /// <summary>
        /// 
        /// </summary>
        /// 
        private string identityColumn;

        /// <summary>
        /// 
        /// </summary>
        /// 
        private EntityDefinition definition;

        /// <summary>
        /// 
        /// </summary>
        /// 
        private GenericActiveRecord activeRecord;

        /// <summary>
        /// 
        /// </summary>
        /// 
        public ActiveRecord()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="database"></param>
        /// 
        public ActiveRecord(string database) 
        {
            activeRecord = new GenericActiveRecord(database);
            EntityAttribute attr = AttributeReflector.GetSingleAttribute<EntityAttribute>(typeof(T));

            if (attr != null)
            {
                entityName = attr.Name;
            }
            else
            {
                entityName = typeof(T).Name;
            }

            IdAttribute iattr = AttributeReflector.GetSinglePropertyAttribute<IdAttribute>(typeof(T));

            if (iattr != null)
            {
                identityColumn = iattr.Name;
            }
            else
            {
                identityColumn = "Id";
            }

            IDictionary<string, ColumnType> columns = AttributeReflector.GetEntityColumns<ColumnAttribute>(typeof(T));
            
            //foreach (KeyValuePair<string, ColumnType> item in columns)
            //{
            //    Console.WriteLine("Column: {0}, Value: {1}", item.Key, item.Value);
            //}

            Console.WriteLine("initializing definition...");
            definition = new EntityDefinition();
            definition.ColumnTypes = columns;
        }

        /// <summary>
        /// 
        /// </summary>
        /// 
        public string Database
        {
            get { return activeRecord.DatabaseInstance; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="reader"></param>
        /// 
        /// <returns></returns>
        /// 
        public abstract T GetEntityMapper(System.Data.IDataReader reader);

        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="id"></param>
        /// 
        /// <returns></returns>
        /// 
        public T Find(long id)
        {
            return activeRecord.Find<T>(string.Format("select * from {0} where {1}= {2}", entityName, identityColumn, id), GetEntityMapper);
        }

        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <returns></returns>
        /// 
        public EntityCollection<T> FindAll()
        {
            return activeRecord.FindAll<T>(string.Format("select * from {0}", entityName), GetEntityMapper);
        }

        public void Delete()
        {
            Console.WriteLine("Delete: {0}", GetValueOfId());

            //return activeRecord.Delete<T>(GenericActiveRecord.DeleteStatement, new SqlParameter[] { new SqlParameter("id", identityColumn) });
        }

        public Object GetValueOfId()
        {
            if (definition == null)
            {
                Console.WriteLine("bailing...");
                return null;

            }

            Object association = typeof(T).GetProperty(identityColumn).GetValue(this, null);
            Console.WriteLine("type: {0}, property: {1}, value: {2}, this: {3}", typeof(T), identityColumn, association, this.GetType().Name);
            
            //Console.WriteLine("Value of ID: {0}", association);

            //IdAttribute iattr = AttributeReflector.GetSinglePropertyAttribute<IdAttribute>(typeof(T));

            //if (iattr != null)
            //{
            //    identityColumn = iattr.Name;
            //}
            //else
            //{
            //    identityColumn = "Id";
            //}

            /*
            foreach (KeyValuePair<string, ColumnType> columnType in definition.ColumnTypes)
            {
                if (columnType.Value.ColumnTypeEnum.Equals(ColumnTypeEnum.ID))
                {
                    return typeof(T).GetProperty(columnType.Value.Property).GetValue(this, null);
                }
            }
            */
            return null;
        }

        //public Object GetValueOfId(EntityDefinition entityDefinition, Object entity)
        //{
        //    foreach (KeyValuePair<string, ColumnType> columnType in entityDefinition.ColumnTypes)
        //    {
        //        if (columnType.Value.ColumnTypeEnum.Equals(ColumnTypeEnum.ID))
        //        {
        //            return entityDefinition.EntityType.GetField(columnType.Value.Property).GetValue(entity);
        //        }
        //    }
            
        //    return null;
        //}
    }
}
